//
//  main.m
//  08-iOS9新特性(Nullability,泛型,_kindof)
//
//  Created by dllo on 16/7/13.
//  Copyright © 2016年 高雅馨. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Person.h"
#import "Truck.h"
#import "Student.h"
int main(int argc, const char * argv[]) {
    // 1. nullability
    Person *per = [[Person alloc] init];
    // nonnull 修饰的属性 对应的(getter 和 setter 方法)
    per.name = nil;
    [per setName:nil];
    per.name = @"🐵";
    [per name];

    // nullable 修饰的属性, 对应的(getter 和 setter 方法)
    // [per setSex:<#(NSString * _Nonnull)#>]
    // [per sex];
    per.sex = nil;
    
    // null_resettable
    // setter 可以为空
    [per setFriends:nil];
    // getter 不可以为空
    [per friends];

    /**
     *  2. 泛型
     * 带泛型的容器(规定了容器中所存储的类型)
     * 声明一个可变数组, 内部存放的都是NSString
     * 1> 数组中添加其他类型, 会有警告
     * 2> 数组取出来的类型不再是id类型, 对应变成声明时的类型
     * 3> 泛型会改变类的一些方法, 使与声明的类型相同
     */
    NSMutableArray<NSString *> *array = [NSMutableArray arrayWithObjects:@"🙈", nil];
    // array.firstObject.length
    [array addObject:@""];
    [array addObject:@20];
    [array addObject:per];
    NSInteger integer = [array objectAtIndex:0].length;
    /**
     *  带泛型的字典
     */
    NSMutableDictionary<NSString *, NSString *> *dic = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"🙈", @"name", nil];
    [dic objectForKey:@"name"].length;

    /**
     *  自定义泛型
     */
    Truck *truck = [[Truck alloc] init];
    Student *stu = [[Student alloc] init];
    stu.stuNumber = @"0304";
    [truck addObject:stu];
    Truck<Student *> *truckStu = [[Truck alloc] init];
    [truckStu addObject:stu];
    [truckStu addObject:per];
    
    // 协变性 与 逆变性
    Truck *truck2 = nil;
    Truck<NSArray *> *truck3 = nil;
    Truck<NSMutableArray *> *truck4 = nil;
    // 大类型(任意类型) 可以给有泛型的赋值
    // 也可以有泛型的给他赋值
    truck2 = truck3;
    truck2 = truck4;
    truck3 = truck2;
    truck4 = truck2;
    // --covariant 协变型 子类给父类赋值是, 自动强转
    // Truck<NSArray *> 与  Truck<NSMutableArray *>
    truck3 = truck4;
    // __contravariant 逆变型  父类给子类赋值, 自行强转(暂时不知道应用何处)
    truck4 = truck3;

    /**
     *  3. __kindof
     * 加__kindof修饰后, 返回的类型及其子类型, 都可以接收这个返回值(避免了一些不必要的强制转换)
     */
    Truck *truckKindOf = [[Truck alloc] init];
   NSMutableArray *arr = [truckKindOf returnArray];
    NSArray *arra = [truckKindOf returnArray];
    return 0;
}
